#ifndef _RINGBUF_H_
#define _RINGBUF_H_

#define Ringbuf_Define(Type, BufName, BufLen) \
        Type BufName##Buf_g[BufLen]; \
        uint32_t BufName##BufSize_g = BufLen; \
        uint32_t BufName##Head_g = 0; \
        uint32_t BufName##Tail_g = 0;

#define Ringbuf_StaticDefine(Type, BufName, BufLen) \
        static Type BufName##Buf_g[BufLen]; \
        static uint32_t BufName##BufSize_g = BufLen; \
        static uint32_t BufName##Head_g = 0; \
        static uint32_t BufName##Tail_g = 0;

#define Ringbuf_IExtern(Type, BufName, BufLen) \
        EXTERN Type BufName##Buf_g[BufLen]; \
        EXTERN uint32_t BufName##BufSize_g; \
        EXTERN uint32_t BufName##Head_g; \
        EXTERN uint32_t BufName##Tail_g;

#define Ringbuf_HeadNextIndex(BufName, N) ((BufName##Head_g + N) % BufName##BufSize_g)
#define Ringbuf_TailNextIndex(BufName, N) ((BufName##Tail_g + N) % BufName##BufSize_g)
#define Ringbuf_HeadPrevIndex(BufName, N) ((BufName##Head_g - N +  BufName##BufSize_g) % BufName##BufSize_g)
#define Ringbuf_TailPrevIndex(BufName, N) ((BufName##Tail_g - N +  BufName##BufSize_g) % BufName##BufSize_g)
#define Ringbuf_Used(BufName) (((BufName##Head_g - BufName##Tail_g)+ BufName##BufSize_g) % BufName##BufSize_g)
#define Ringbuf_BufSize(BufName) BufName##BufSize_g
#define Ringbuf_TailNext(BufName, N) BufName##Buf_g[Ringbuf_TailNextIndex(BufName, N)]
#define Ringbuf_HeadPrev(BufName, N) BufName##Buf_g[Ringbuf_HeadPrevIndex(BufName, N)]
#define Ringbuf_AddData(BufName, Data) BufName##Buf_g[BufName##Head_g] = Data; \
                                       BufName##Head_g = Ringbuf_HeadNextIndex(BufName, 1);
#define Ringbuf_GetData(BufName) BufName##Buf_g[BufName##Tail_g]
#define Ringbuf_DelData(BufName, N) BufName##Tail_g = Ringbuf_TailNextIndex(BufName, N);
#define Ringbuf_IsFull(BufName) (BufName##Tail_g == Ringbuf_HeadNextIndex(BufName, 1))
#define Ringbuf_IsNull(BufName) (BufName##Tail_g == BufName##Head_g)

#endif